package com.hqd.ch03.v25.spel.parse;

import com.hqd.ch03.v25.spel.Expression;
import com.hqd.ch03.v25.spel.ExpressionParser;
import com.hqd.ch03.v25.spel.ParserContext;
import com.hqd.ch03.v25.spel.express.CompositeStringExpression;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * Spel表达式抽象类
 */
public abstract class TemplateAwareExpressionParser implements ExpressionParser {
    @Override
    public Expression parseExpression(String expressionString) {
        return parseExpression(expressionString, null);
    }

    @Override
    public Expression parseExpression(String expressionString, ParserContext context) {
        /**
         * 按模板解析
         */
        if (context != null && context.isTemplate()) {
            return parseTemplate(expressionString, context);
        } else {
            //不用模板，直接解析
            return doParseExpression(expressionString, context);
        }
    }

    protected abstract Expression doParseExpression(String expressionString, ParserContext context);

    protected Expression parseTemplate(String expressionString, ParserContext context) {
        List<Expression> expressions = new ArrayList<>();
        String prefix = context.getExpressionPrefix();
        String suffix = context.getExpressionSuffix();
        int startIdx = 0;

        /**
         * 解析字符串中的表达式
         */
        while (startIdx < expressionString.length()) {
            int prefixIndex = expressionString.indexOf(prefix, startIdx);
            if (prefixIndex >= startIdx) {
                //说明中间有其他字符，直接解析
                if (prefixIndex > startIdx) {
                    expressions.add(new LiteralExpression(expressionString.substring(startIdx, prefixIndex)));
                }
                int afterPrefixIndex = prefixIndex + prefix.length();
                int suffixIndex = expressionString.indexOf(suffix, afterPrefixIndex);
                if (suffixIndex == -1) {
                    throw new RuntimeException(String.format("缺失:%s", suffix));
                }
                /**
                 * 截取子串
                 */
                String expr = expressionString.substring(prefixIndex + prefix.length(), suffixIndex);
                expr = expr.trim();
                if (StringUtils.isBlank(expr)) {
                    throw new RuntimeException("expr 表达式为空");
                }
                expressions.add(doParseExpression(expr, context));
                startIdx = suffixIndex + suffix.length();
            } else {
                expressions.add(new LiteralExpression(expressionString.substring(startIdx)));
                startIdx = expressionString.length();
            }
        }
        if (CollectionUtils.isNotEmpty(expressions)) {
            if (expressions.size() == 1) {
                return expressions.get(0);
            } else {
                return new CompositeStringExpression(expressionString, expressions.toArray(new Expression[0]));
            }
        }
        return null;
    }


}
